1 Weex Android的集成
具体过程可以查看官方文档
1.1 在app运行的初始阶段对Weex Engine进行初始化:
1 | //MyApplication.java |
1.1.1 WXSDKEngine.java中的源码初始化部分
1 | /** |
主要操作
- 初始化so库文件,渲染逻辑、脚本业务框架等都封装在了这里;
- 初始化initScriptsFramework,也就是初始化脚本框架;
- register() 注册component、module
1.2 生成SDK实例,开始渲染bundle.js,并且监听渲染完事件,添加到container中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25//MainActivity.java
public class MainActivity extends AppCompatActivity implements IWXRenderListener {
public static final String TAG = "MainActivity";
WXSDKInstance mInstance;
ViewGroup mContainer;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (ViewGroup) findViewById(R.id.container);
mInstance = new WXSDKInstance(this); //create weex instance
mInstance.registerRenderListener(this);
//mInstance.registerRenderListener(new SimpleRenderListener()) //SimpleRenderListener需要开发者来实现
instance.renderByUrl(TAG, WEEX_INDEX_URL, options, null, ScreenUtil.getDisplayWidth(this),
ScreenUtil.getDisplayHeight(this), WXRenderStrategy.APPEND_ASYNC);
...
...
//监听创建完命令,然后添加到container中
public void onViewCreated(WXSDKInstance wxsdkInstance, View view) {
if (mContainer != null) {
mContainer.addView(view);
}
}
2 具体渲染源码
2.1 源码中的renderByUrl函数
1 | //WXSDKInstance.java |
如果是file那就直接调用render函数渲染,如果是远程地址,用http请求,在请求结束的回调中去渲染,WXHttpListener继承自IWXHttpAdapter.OnHttpListener,其有onHttpFinish回调1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public void onHttpFinish(WXResponse response) {
mWXPerformance.networkTime = System.currentTimeMillis() - startRequestTime;
if(response.extendParams!=null){
Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;
WXLogUtils.renderPerformanceLog("actualNetworkTime", mWXPerformance.actualNetworkTime);
Object pureNetworkTime=response.extendParams.get("pureNetworkTime");
mWXPerformance.pureNetworkTime=pureNetworkTime instanceof Long?(long)pureNetworkTime:0;
WXLogUtils.renderPerformanceLog("pureNetworkTime", mWXPerformance.pureNetworkTime);
Object connectionType=response.extendParams.get("connectionType");
mWXPerformance.connectionType=connectionType instanceof String?(String)connectionType:"";
Object packageSpendTime=response.extendParams.get("packageSpendTime");
mWXPerformance.packageSpendTime=packageSpendTime instanceof Long ?(long)packageSpendTime:0;
Object syncTaskTime=response.extendParams.get("syncTaskTime");
mWXPerformance.syncTaskTime=syncTaskTime instanceof Long ?(long)syncTaskTime:0;
Object requestType=response.extendParams.get("requestType");
mWXPerformance.requestType=requestType instanceof String?(String)requestType:"";
}
WXLogUtils.renderPerformanceLog("networkTime", mWXPerformance.networkTime);
if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
String template = new String(response.originalData);
render(pageName, template, options, jsonInitData, width, height, flag);
} else if (TextUtils.equals(WXRenderErrorCode.WX_USER_INTERCEPT_ERROR, response.statusCode)) {
WXLogUtils.d("user intercept");
onRenderError(WXRenderErrorCode.WX_USER_INTERCEPT_ERROR,response.errorMsg);
} else {
onRenderError(WXRenderErrorCode.WX_NETWORK_ERROR, response.errorMsg);
}
}
最终还是调用render函数进行渲染1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public void render(String pageName, String template, Map<String, Object> options, String jsonInitData, int width, int height, WXRenderStrategy flag) {
if (mRendered || TextUtils.isEmpty(template)) {
return;
}
if(options==null){
options=new HashMap<>();
}
if(WXEnvironment.sDynamicMode && !TextUtils.isEmpty(WXEnvironment.sDynamicUrl) && options!=null && options.get("dynamicMode")==null){
options.put("dynamicMode","true");
renderByUrl(pageName, WXEnvironment.sDynamicUrl, options, jsonInitData, width, height, flag);
return;
}
mWXPerformance.pageName = pageName;
mWXPerformance.JSTemplateSize = template.length() / 1024;
mRenderStartTime = System.currentTimeMillis();
mRenderStrategy = flag;
mGodViewWidth = width;
mGodViewHeight = height;
mInstanceId = WXSDKManager.getInstance().generateInstanceId();
WXSDKManager.getInstance().createInstance(this, template, options, jsonInitData);
mRendered = true;
}
render函数中关键的一步
其实是create了一个WXSDKManager的实例,并且把template传了过去1
WXSDKManager.getInstance().createInstance(this, template, options, jsonInitData);
2.2 WXSDKManager
创建WXSDKManager实例函数主要是创建了WXRenderManger和WXBridgeManger的实例,template是传递到了WXBridgeManger的实例1
2
3
4
5//WXSDKManager.java
void createInstance(WXSDKInstance instance, String code, Map<String, Object> options, String jsonInitData) {
mWXRenderManager.createInstance(instance);
mBridgeManager.createInstance(instance.getInstanceId(), code, options, jsonInitData);
}
WXRenderManger创建实例只是把实例id和状态管理实例push到它的ConcurrentHashMap<String, WXRenderStatement> mRegistries中,为了便于管理多实例的情况1
2
3
4//mWXRenderManager.java
public void createInstance(WXSDKInstance instance) {
mRegistries.put(instance.getInstanceId(), new WXRenderStatement(instance));
}
WXBridgeManager的实例化,执行了一个post函数,启动一个线程执行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34//WXBridgeManager.java
/**
* Create instance.
*/
public void createInstance(final String instanceId, final String template,
final Map<String, Object> options, final String data) {
if ( TextUtils.isEmpty(instanceId)
|| TextUtils.isEmpty(template) || mJSHandler == null) {
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
if (instance != null) {
instance.onRenderError(WXRenderErrorCode.WX_CREATE_INSTANCE_ERROR, "createInstance fail!");
}
return;
}
post(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
invokeCreateInstance(instanceId, template, options, data);
final long totalTime = System.currentTimeMillis() - start;
WXSDKManager.getInstance().postOnUiThread(new Runnable() {
@Override
public void run() {
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
if (instance != null) {
instance.createInstanceFinished(totalTime);
}
}
}, 0);
}
}, instanceId);
}
run函数内先是执行了invokeCreateInstance1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53private void invokeCreateInstance(String instanceId, String template,
Map<String, Object> options, String data) {
initFramework("");
if (mMock) {
mock(instanceId);
} else {
if (!isJSFrameworkInit()) {
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
if (instance != null) {
instance.onRenderError(WXRenderErrorCode.WX_CREATE_INSTANCE_ERROR, "createInstance "
+ "fail!");
}
String err = "[WXBridgeManager] invokeCreateInstance: framework.js uninitialized.";
WXErrorCode.WX_ERR_INVOKE_NATIVE.appendErrMsg(err);
commitJSBridgeAlarmMonitor(instanceId, WXErrorCode.WX_ERR_INVOKE_NATIVE);
WXLogUtils.e(err);
return;
}
try {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.d("createInstance >>>> instanceId:" + instanceId
+ ", options:"
+ WXJsonUtils.fromObjectToJSONString(options)
+ ", data:" + data);
}
WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String,
instanceId);
WXJSObject instanceObj = new WXJSObject(WXJSObject.String,
template);
WXJSObject optionsObj = new WXJSObject(WXJSObject.JSON,
options == null ? "{}"
: WXJsonUtils.fromObjectToJSONString(options));
WXJSObject dataObj = new WXJSObject(WXJSObject.JSON,
data == null ? "{}" : data);
WXJSObject[] args = {instanceIdObj, instanceObj, optionsObj,
dataObj};
invokeExecJS(instanceId, null, METHOD_CREATE_INSTANCE, args);
commitJSBridgeAlarmMonitor(instanceId, WXErrorCode.WX_SUCCESS);
} catch (Throwable e) {
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
if (instance != null) {
instance.onRenderError(WXRenderErrorCode.WX_CREATE_INSTANCE_ERROR,
"createInstance failed!");
}
String err = "[WXBridgeManager] invokeCreateInstance " + e.getCause();
WXErrorCode.WX_ERR_INVOKE_NATIVE.appendErrMsg(err);
commitJSBridgeAlarmMonitor(instanceId, WXErrorCode.WX_ERR_INVOKE_NATIVE);
WXLogUtils.e(err);
}
}
}
它把之前传过来的参数又包装了以下,传给invokeExecJS执行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15private void invokeExecJS(String instanceId, String namespace, String function, WXJSObject[] args){
if (WXEnvironment.isApkDebugable()) {
mLodBuilder.append("callJS >>>> instanceId:").append(instanceId)
.append("function:").append(function)
.append(" tasks:").append(WXJsonUtils.fromObjectToJSONString(args));
WXLogUtils.d(mLodBuilder.substring(0));
mLodBuilder.setLength(0);
}
if(mDestroyedInstanceId!=null && !mDestroyedInstanceId.contains(instanceId)) {
mWXBridge.execJS(instanceId, namespace, function, args);
}else{
WXLogUtils.w("invokeExecJS: instanceId: "+instanceId+"was destroy !! ExecJS abandon !!");
}
}
mWXBridge是WXBridge的实例,执行execJS调用so库方法进行js代码解析,在安卓中就是V8引擎,解析完后c++代码会调用callNative函数,将js中对native的操作告诉native,最终实现native端的渲染。
2.3 native中处理v8引擎解析的js代码产生的回调,从而实现js–>native
1 | public int callNative(String instanceId, String tasks, String callback) { |
它又调用了WXBridgeManager的callNative1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96public int callNative(String instanceId, String tasks, String callback) {
if (TextUtils.isEmpty(tasks)) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e("[WXBridgeManager] callNative: call Native tasks is null");
}
return INSTANCE_RENDERING_ERROR;
}
if (WXEnvironment.isApkDebugable()) {
mLodBuilder.append("[WXBridgeManager] callNative >>>> instanceId:").append(instanceId)
.append(", tasks:").append(tasks).append(", callback:").append(callback);
WXLogUtils.d(mLodBuilder.substring(0));
mLodBuilder.setLength(0);
}
if(mDestroyedInstanceId!=null &&mDestroyedInstanceId.contains(instanceId)){
return DESTROY_INSTANCE;
}
long start = System.currentTimeMillis();
JSONArray array = JSON.parseArray(tasks);
if(WXSDKManager.getInstance().getSDKInstance(instanceId)!=null) {
WXSDKManager.getInstance().getSDKInstance(instanceId).jsonParseTime(System.currentTimeMillis() - start);
}
int size = array.size();
if (size > 0) {
try {
JSONObject task;
for (int i = 0; i < size; ++i) {
task = (JSONObject) array.get(i);
if (task != null && WXSDKManager.getInstance().getSDKInstance(instanceId) != null) {
if (TextUtils.equals(WXDomModule.WXDOM, (String) task.get(WXDomModule.MODULE))) {
sDomModule = getDomModule(instanceId);
sDomModule.callDomMethod(task);
} else {
WXModuleManager.callModuleMethod(instanceId, (String) task.get(WXDomModule.MODULE),
(String) task.get(WXDomModule.METHOD), (JSONArray) task.get(WXDomModule.ARGS));
}
}
}
} catch (Exception e) {
WXLogUtils.e("[WXBridgeManager] callNative exception: ", e);
}
}
if (UNDEFINED.equals(callback)) {
return INSTANCE_RENDERING_ERROR;
}
// get next tick
getNextTick(instanceId, callback);
return INSTANCE_RENDERING;
}
private void getNextTick(final String instanceId, final String callback) {
addJSTask(METHOD_CALLBACK,instanceId, callback, "{}");
sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH);
}
private void addJSTask(final String method, final String instanceId, final Object... args) {
mJSHandler.post(new Runnable() {
@Override
public void run() {
if (args == null || args.length == 0) {
return;
}
ArrayList<Object> argsList = new ArrayList<>();
for (Object arg : args) {
argsList.add(arg);
}
WXHashMap<String, Object> task = new WXHashMap<>();
task.put(WXConst.KEY_METHOD, method);
task.put(WXConst.KEY_ARGS, argsList);
if (mNextTickTasks.get(instanceId) == null) {
ArrayList<WXHashMap<String, Object>> list = new ArrayList<>();
list.add(task);
mNextTickTasks.put(instanceId, list);
} else {
mNextTickTasks.get(instanceId).add(task);
}
}
});
}
private void sendMessage(String instanceId, int what) {
Message msg = Message.obtain(mJSHandler);
msg.obj = instanceId;
msg.what = what;
msg.sendToTarget();
}
在这个callNative函数中会分发task,并且获取getNextTick。tasks中就包含各种函数,下面的callDomMethod会进行判断,从而调用native中的对应方法
2.4 WXDOMModule.java
1 | public void callDomMethod(JSONObject task) { |
3 渲染举例
当method是CREATE_BODY时,会执行createBody函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* Create a body for the current {@link com.taobao.weex.WXSDKInstance} according to given
* parameter.
* @param element info about how to create a body
*/
public void createBody(JSONObject element) {
if (element == null) {
return;
}
Message msg = Message.obtain();
WXDomTask task = new WXDomTask();
task.instanceId = mWXSDKInstance.getInstanceId();
task.args = new ArrayList<>();
task.args.add(element);
msg.what = WXDomHandler.MsgType.WX_DOM_CREATE_BODY;
msg.obj = task;
WXSDKManager.getInstance().getWXDomManager().sendMessage(msg);
}
上面这个函数最终是调用了WXDOMManager中的sendMessage函数1
2
3
4
5
6
7public void sendMessage(Message msg) {
if (msg == null || mDomHandler == null || mDomThread == null
|| !mDomThread.isWXThreadAlive() || mDomThread.getLooper() == null) {
return;
}
mDomHandler.sendMessage(msg);
}
从代码中可以看到WXDOMManager中其实又是执行了mDomHandler的sendMessage。WXDomHandler负责响应消息,并且分发任务,
它继承了os.handler.callback。它会处理消息,最终createBody被分发到mWXDomManager.createBody,Manger中又是调用了
WXDOMStatement.createBody(element);下面看WXDOmStatement的createBody函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80//WXDOMStatement.java
/**
* Create command object for creating body according to the JSONObject. And put the command
* object in the queue.
* @param element the jsonObject according to which to create command object.
*/
void createBody(JSONObject element) {
if (mDestroy) {
return;
}
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(mInstanceId);
if (element == null) {
if (instance != null) {
instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_ERR_DOM_CREATEBODY);
}
return;
}
//Parse the jsonObject to {@link WXDomObject} recursively
WXDomObject domObject = parseInner(element);
if(domObject==null){
return;
}
Map<String, Object> style = new HashMap<>(5);
if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_FLEXDIRECTION)) {
style.put(WXDomPropConstant.WX_FLEXDIRECTION, "column");
}
if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_BACKGROUNDCOLOR)) {
style.put(WXDomPropConstant.WX_BACKGROUNDCOLOR, "#ffffff");
}
//If there is height or width in JS, then that value will override value here.
if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_WIDTH)) {
style.put(WXDomPropConstant.WX_WIDTH, WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexWidth(mInstanceId)));
domObject.setModifyWidth(true);
}
if (domObject.style == null || !domObject.style.containsKey(WXDomPropConstant.WX_HEIGHT)) {
style.put(WXDomPropConstant.WX_HEIGHT, WXViewUtils.getWebPxByWidth(WXViewUtils.getWeexHeight(mInstanceId)));
domObject.setModifyHeight(true);
}
domObject.ref = WXDomObject.ROOT;
domObject.updateStyle(style);
transformStyle(domObject, true);
try {
final WXComponent component = mWXRenderManager.createBodyOnDomThread(mInstanceId, domObject);
AddDomInfo addDomInfo = new AddDomInfo();
addDomInfo.component = component;
mAddDom.put(domObject.ref, addDomInfo);
mNormalTasks.add(new IWXRenderTask() {
public void execute() {
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(mInstanceId);
if (instance == null || instance.getContext() == null) {
WXLogUtils.e("instance is null or instance is destroy!");
return;
}
try {
mWXRenderManager.createBody(mInstanceId, component);
} catch (Exception e) {
WXLogUtils.e("create body failed.", e);
}
}
public String toString() {
return "createBody";
}
});
animations.add(new Pair<String, Map<String, Object>>(domObject.ref,domObject.style));
mDirty = true;
if (instance != null) {
instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_SUCCESS);
}
}catch (Exception e){
WXLogUtils.e("create body in dom thread failed." + e.getMessage());
}
}
这个函数中有一句parseInner函数把element这个JSONObject转换成domObject,给他加上了各种type、
event、childern等属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50/**
* Parse the jsonObject to {@link WXDomObject} recursively
* @param map the original JSONObject
* @return Dom Object corresponding to the JSONObject.
*/
private WXDomObject parseInner(JSONObject map) {
if (map == null || map.size() <= 0) {
return null;
}
String type = (String) map.get("type");
WXDomObject domObject = WXDomObjectFactory.newInstance(type);
if(domObject==null){
return null;
}
domObject.type = type;
domObject.ref = (String) map.get("ref");
Object style = map.get("style");
if (style != null && style instanceof JSONObject) {
domObject.style = new WXStyle();
putAll(domObject.style, (JSONObject) style);
}
Object attr = map.get("attr");
if (attr != null && attr instanceof JSONObject) {
domObject.attr = new WXAttr();
putAll(domObject.attr, (JSONObject) attr);
}
Object event = map.get("event");
if (event != null && event instanceof JSONArray) {
domObject.event = new WXEvent();
JSONArray eventArray = (JSONArray) event;
int count = eventArray.size();
for (int i = 0; i < count; ++i) {
domObject.event.add(eventArray.getString(i));
}
}
Object children = map.get("children");
if (children != null && children instanceof JSONArray) {
domObject.children = new ArrayList<>();
JSONArray childrenArray = (JSONArray) children;
int count = childrenArray.size();
for (int i = 0; i < count; ++i) {
domObject.children.add(parseInner(childrenArray.getJSONObject(i)));
}
}
return domObject;
}
这createBody函数就是根据JSONObject创建一个创建body的命令并且推到队列中。
队列里会执行这么一句话,执行了mWXRenderManager的createBodyOnDomThread函数1
final WXComponent component = mWXRenderManager.createBodyOnDomThread(mInstanceId, domObject);
看WXRenderManager中的createBodyOnDomThread函数1
2
3
4
5
6
7public WXComponent createBodyOnDomThread(String instanceId, WXDomObject domObject) {
WXRenderStatement statement = mRegistries.get(instanceId);
if (statement == null) {
return null;
}
return statement.createBodyOnDomThread(domObject);
}
又是调用了WXRenderStatement中的对应函数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26WXComponent createBodyOnDomThread(WXDomObject dom) {
if (mWXSDKInstance == null) {
return null;
}
WXDomObject domObject = new WXDomObject();
domObject.type = WXBasicComponentType.DIV;
domObject.ref = "god";
mGodComponent = (WXVContainer) WXComponentFactory.newInstance(mWXSDKInstance, domObject, null);
mGodComponent.createView(null, -1);
if (mGodComponent == null) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e("rootView failed!");
}
//TODO error callback
return null;
}
FrameLayout frameLayout = (FrameLayout) mGodComponent.getHostView();
ViewGroup.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
frameLayout.setLayoutParams(layoutParams);
frameLayout.setBackgroundColor(Color.TRANSPARENT);
WXComponent component = generateComponentTree(dom, mGodComponent);
mGodComponent.addChild(component);
mRegistry.put(component.getRef(), component);
return component;
}
这个函数就是创建WXComponent,但是component是由其中generateComponentTree这个函数是把之前传进来的WXDomObject转换成Component的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22private WXComponent generateComponentTree(WXDomObject dom, WXVContainer parent) {
if (dom == null || parent == null) {
return null;
}
WXComponent component = WXComponentFactory.newInstance(mWXSDKInstance, dom,
parent, parent.isLazy());
mRegistry.put(dom.ref, component);
if (component instanceof WXVContainer) {
WXVContainer parentC = (WXVContainer) component;
int count = dom.childCount();
WXDomObject child = null;
for (int i = 0; i < count; ++i) {
child = dom.getChild(i);
if (child != null) {
parentC.addChild(generateComponentTree(child, parentC));
}
}
}
return component;
}
终于得到WXComponent后,在WXDOMStatement.createBody中接着就执行了
mWXRenderManager.createBody(mInstanceId, component);同样的它又
是调用了statement.createBody(component);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/**
* create RootView ,every weex Instance View has a rootView;
* @see com.taobao.weex.dom.WXDomStatement#createBody(JSONObject)
*/
void createBody(WXComponent component) {
long start = System.currentTimeMillis();
component.createView(mGodComponent, -1);
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.renderPerformanceLog("createView", (System.currentTimeMillis() - start));
}
start = System.currentTimeMillis();
component.applyLayoutAndEvent(component);
component.bindData(component);
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.renderPerformanceLog("bind", (System.currentTimeMillis() - start));
}
if (component instanceof WXScroller) {
WXScroller scroller = (WXScroller) component;
if (scroller.getInnerView() instanceof ScrollView) {
mWXSDKInstance.setRootScrollView((ScrollView) scroller.getInnerView());
}
}
mWXSDKInstance.setRootView(mGodComponent.getRealView());
if (mWXSDKInstance.getRenderStrategy() != WXRenderStrategy.APPEND_ONCE) {
mWXSDKInstance.onViewCreated(mGodComponent);
}
}
最终这两句话创建rootview并且触发mWXSDKInstance的onViewCreated1
2
3
4mWXSDKInstance.setRootView(mGodComponent.getRealView());
if (mWXSDKInstance.getRenderStrategy() != WXRenderStrategy.APPEND_ONCE) {
mWXSDKInstance.onViewCreated(mGodComponent);
}
4 渲染结束调用过程
4.1 当method是CREATE_FINISH时,调用createFinish
1 | /** |
getWXDomManager的sendMessage调用了mDomHandler.sendMessage(msg);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111WXDomHandler.java
/**
* Handler for dom operations.
*/
public class WXDomHandler implements Handler.Callback {
/**
* The batch operation in dom thread will run at most once in 16ms.
*/
private static final int DELAY_TIME = 16;//ms
private WXDomManager mWXDomManager;
private boolean mHasBatch = false;
public WXDomHandler(WXDomManager domManager) {
mWXDomManager = domManager;
}
@Override
public boolean handleMessage(Message msg) {
if (msg == null) {
return false;
}
int what = msg.what;
Object obj = msg.obj;
WXDomTask task = null;
if (obj instanceof WXDomTask) {
task = (WXDomTask) obj;
}
if (!mHasBatch) {
mHasBatch = true;
mWXDomManager.sendEmptyMessageDelayed(WXDomHandler.MsgType.WX_DOM_BATCH, DELAY_TIME);
}
switch (what) {
case MsgType.WX_DOM_CREATE_BODY:
mWXDomManager.createBody(task.instanceId, (JSONObject) task.args.get(0));
break;
case MsgType.WX_DOM_UPDATE_ATTRS:
mWXDomManager.updateAttrs(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1));
break;
case MsgType.WX_DOM_UPDATE_STYLE:
mWXDomManager.updateStyle(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1));
break;
case MsgType.WX_DOM_ADD_DOM:
mWXDomManager.addDom(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1), (Integer) task.args.get(2));
break;
case MsgType.WX_DOM_REMOVE_DOM:
mWXDomManager.removeDom(task.instanceId, (String) task.args.get(0));
break;
case MsgType.WX_DOM_MOVE_DOM:
mWXDomManager.moveDom(task.instanceId, (String) task.args.get(0), (String) task.args.get(1), (Integer) task.args.get(2));
break;
case MsgType.WX_DOM_ADD_EVENT:
mWXDomManager.addEvent(task.instanceId, (String) task.args.get(0), (String) task.args.get(1));
break;
case MsgType.WX_DOM_REMOVE_EVENT:
mWXDomManager.removeEvent(task.instanceId, (String) task.args.get(0), (String) task.args.get(1));
break;
case MsgType.WX_DOM_CREATE_FINISH:
mWXDomManager.createFinish(task.instanceId);
break;
case MsgType.WX_DOM_REFRESH_FINISH:
mWXDomManager.refreshFinish(task.instanceId);
break;
case MsgType.WX_DOM_UPDATE_FINISH:
mWXDomManager.updateFinish(task.instanceId);
break;
case MsgType.WX_ANIMATION:
mWXDomManager.startAnimation(task.instanceId,
(String) task.args.get(0),
(String) task.args.get(1),
(String) task.args.get(2));
break;
case MsgType.WX_DOM_BATCH:
mWXDomManager.batch();
mHasBatch = false;
break;
case MsgType.WX_DOM_SCROLLTO:
mWXDomManager.scrollToDom(task.instanceId, (String) task.args.get(0), (JSONObject) task.args.get(1));
break;
case MsgType.WX_DOM_ADD_RULE:
mWXDomManager.addRule((String) task.args.get(0), (JSONObject) task.args.get(1));
break;
default:
break;
}
return true;
}
public static class MsgType {
public static final int WX_DOM_CREATE_BODY = 0x0;
public static final int WX_DOM_UPDATE_ATTRS = 0x01;
public static final int WX_DOM_UPDATE_STYLE = 0x02;
public static final int WX_DOM_ADD_DOM = 0x03;
public static final int WX_DOM_REMOVE_DOM = 0x04;
public static final int WX_DOM_MOVE_DOM = 0x05;
public static final int WX_DOM_ADD_EVENT = 0x06;
public static final int WX_DOM_REMOVE_EVENT = 0x07;
public static final int WX_DOM_SCROLLTO = 0x08;
public static final int WX_DOM_CREATE_FINISH = 0x09;
public static final int WX_DOM_REFRESH_FINISH = 0x0a;
public static final int WX_DOM_UPDATE_FINISH = 0x0b;
public static final int WX_ANIMATION=0xc;
public static final int WX_DOM_ADD_RULE=0xd;
public static final int WX_DOM_BATCH = 0xff;
}
}
最终调用了mWXDomManager中的对应方法,而WXDomManager中最终又调用了WXDomStatement中的对应方法。
4.2 WXDomStatement.java
weex.dom.WXDomStatement调用createFinish,通知WXRenderManager,given view is finished1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31/**
* Create a command object for notifying {@link WXRenderManager} that the process of creating
* given view is finished, and put the command object in the queue.
*/
void createFinish() {
if (mDestroy) {
return;
}
final WXDomObject root = mRegistry.get(WXDomObject.ROOT);
mNormalTasks.add(new IWXRenderTask() {
public void execute() {
mWXRenderManager.createFinish(mInstanceId,
(int) root.getLayoutWidth(),
(int) root.getLayoutHeight());
}
public String toString() {
return "createFinish";
}
});
mDirty = true;
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(mInstanceId);
if (instance != null) {
instance.commitUTStab(WXConst.DOM_MODULE, WXErrorCode.WX_SUCCESS);
}
}
4.3 渲染完触发回调
WXRenderStatement调用createFinish,触发mWXSDKInstance.onViewCreated(mGodComponent);